package cn.imatu.framework.ip2region.config;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.imatu.framework.core.constant.*;
import cn.imatu.framework.ip2region.config.properties.*;
import cn.imatu.framework.ip2region.constants.*;
import cn.imatu.framework.ip2region.handler.*;
import cn.imatu.framework.tool.core.exception.Assert;
import lombok.extern.slf4j.Slf4j;
import org.lionsoul.ip2region.xdb.Searcher;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.io.File;

/**
 * <a href="https://gitee.com/lionsoul/ip2region">ip2region官网</a>
 *
 * @author shenguangyang
 */
@Slf4j
@Component
@ConditionalOnClass(Searcher.class)
@ConditionalOnProperty(prefix = LyCoreConstants.PROPERTIES_PRE + "ip2region", value = "type", havingValue = IpOfflineType.IP2REGION)
public class LyIp2RegionAutoConfiguration {
    @Resource
    private LyIpProperties lyIpProperties;
    private byte[] vectorIndex;

    @PostConstruct
    public void init() {
        // 从 dbPath 中预先加载 VectorIndex 缓存，并且把这个得到的数据作为全局变量，后续反复使用。
        String databasePath = lyIpProperties.getDatabasePath();
        String downloadUrl = lyIpProperties.getDownloadUrl();
        Assert.notEmpty(databasePath, "databasePath 不能为空");
        if (!FileUtil.exist(new File(databasePath))) {
            log.info("databasePath [{}] not exist, download from [{}]", databasePath, downloadUrl);
            if (StrUtil.isEmpty(downloadUrl)) {
                throw new RuntimeException("download ip2region fail, downloadUrl is empty");
            }

            FileUtil.mkParentDirs(databasePath);
            byte[] bytes = HttpUtil.downloadBytes(databasePath);
            FileUtil.writeBytes(bytes, new File(databasePath));
            log.info("databasePath [{}] download success", databasePath);
        }
        try {
            vectorIndex = Searcher.loadVectorIndexFromFile(databasePath);
        } catch (Exception e) {
            log.error("failed to load vector index from [{}]: ", databasePath, e);
        }
    }

    @Bean
    @ConditionalOnMissingBean
    public Ip2RegionHandler ip2RegionOfflineHandler() {
        String databasePath = lyIpProperties.getDatabasePath();
        return new Ip2RegionImpl(vectorIndex, databasePath);
    }

}
